<template>
  <a-row ref="el" v-bind="$attrs" :gutter="sidebar?10:0" :style="sidebar && scroll.y?'maxHeight:'+scroll.y+'px':''">
    <a-col v-if="sidebar" :md="sidebar.attribute.span" :sm="24" :xs="24" >
      <div style="height: 100%">
        <render :data="sidebar" v-model:value="sidebarValue"></render>
      </div>
    </a-col>
    <a-col :md="sidebar?(24-sidebar.attribute.span):24" :sm="24" :xs="24">
      <div style="height: 100%">
      <!-- 工具栏 -->
      <div v-if="!hideTools" :class="['tools',custom && custom.attribute.customStyle != 'card'?'custom':'']">
        <div class="left">
          <render :data="selectionActions" v-if="selectIds.length > 0">
            <a-button style="margin-right: 8px">
              {{ trans('Grid.selectedTotal',{total:selectIds.length}) }}
              <DownOutlined v-if="selectionActions"/>
            </a-button>
          </render>
          <a-input-search
              class="quickSearch"
              v-if="quickSearch"
              allowClear
              :enter-button="trans('Grid.search')"
              v-model:value="quickSearchValue"
              :placeholder="quickSearchText || trans('Grid.quickSearchText')"
              @search="handleFilter">
            <template #prefix>
              <search-outlined style="color: #c0c4cc;"/>
            </template>
          </a-input-search>
          <!--添加-->
          <render v-if="addButton && !hideAdd" :data="addButton"></render>
          <!--导出 -->
          <a-dropdown :trigger="['click']" v-if="!hideExport">
            <template #overlay>
              <a-menu @click="handleExport">
                <a-menu-item key="page" v-if="!hideExportCurrentPage">
                  {{ trans('Grid.exportPage') }}
                </a-menu-item>
                <a-menu-item key="select" :disabled="selectIds.length === 0" v-if="!hideExportSelection">
                  {{ trans('Grid.exportSelect') }}
                </a-menu-item>
                <a-menu-item key="all" v-if="!hideExportAll">
                  {{ trans('Grid.exportAll') }}
                </a-menu-item>
              </a-menu>
            </template>
            <a-button type="primary">
              <template #icon>
                <download-outlined/>
              </template>
              {{ trans('Grid.export') }}
              <DownOutlined/>
            </a-button>
          </a-dropdown>
          <!--删除选中-->
          <a-button v-if="!hideDeleteSelection && selectIds.length > 0 && !trashed" @click="deleteSelect">
            <template #icon>
              <delete-outlined/>
            </template>
            {{ trans('Grid.deleteSelected') }}
          </a-button>
          <!--恢复选中-->
          <a-button v-if="!hideTrashedRestore && selectIds.length > 0 && trashed" @click="recoverySelect">
            <template #icon>
              <diff-outlined/>
            </template>
            {{ trans('Grid.restoreSelected') }}
          </a-button>
          <!--删除全部-->
          <a-button @click="deleteAll" type="primary" danger v-if="!hideDelete && !(trashed && hideTrashedDelete)">
            <template #icon>
              <delete-outlined/>
            </template>
            {{ trans('Grid.clearData') }}
          </a-button>
          <!-- tools -->
          <render v-for="tool in tools" :data="tool"></render>
        </div>
        <div class="right">
          <!-- 筛选工具 -->
          <a-tooltip :title="expandFormFilter?trans('Grid.collapseFilter'):trans('Grid.expandFilter')"
                     v-if="filter && !hideFilter">
            <a-button shape="circle" size="small" @click="visibleFilter">
              <template #icon>
                <SearchOutlined/>
              </template>
            </a-button>
          </a-tooltip>
          <!-- 回收站 -->
          <a-tooltip :title="trashed?trans('Grid.dataList'):trans('Grid.recycle')" v-if="!hideTrashed">
            <a-button shape="circle" size="small" @click="trashedHandel">
              <template #icon>
                <appstore-filled v-if="trashed"/>
                <delete-outlined v-else/>
              </template>
            </a-button>
          </a-tooltip>
          <!-- 刷新 -->
          <a-button shape="circle" size="small" @click="refresh" v-if="!hideRefresh">
            <template #icon>
              <reload-outlined/>
            </template>
          </a-button>
          <a-dropdown v-model:visible="checkboxColumnVisible" v-if="!custom" :trigger="['click']">
            <a-button shape="circle" size="small" @click.prevent>
              <template #icon>
                <appstore-filled/>
              </template>
            </a-button>
            <template #overlay>
                  <a-menu>
                    <a-menu-item>
                      <a-input
                          @change="checkboxColumnSearch"
                          allowClear
                          :placeholder="trans('Grid.quickSearchText')">
                        <template #prefix>
                          <search-outlined style="color: #c0c4cc;"/>
                        </template>
                      </a-input>
                    </a-menu-item>
                    <draggable :list="checkboxColumns" item-key="dataIndex"  animation="300" handle=".sortHandel">
                      <template #item="{ element }">
                        <div>
                          <a-menu-item v-if="element.title && element.checkboxColumnShow" :key="element.dataIndex">
                            <template #icon>
                              <drag-outlined class="sortHandel" style="font-weight:bold;cursor: grab"/>
                            </template>
                            <div class="checkbox-column-content">
                              <span>{{ element.title }}</span>
                              <a-switch size="small" v-model:checked="element.hide" :checkedValue="false" :unCheckedValue="true" />
                            </div>
                          </a-menu-item>
                        </div>
                      </template>
                    </draggable>
                    <a-menu-divider></a-menu-divider>
                    <div class="checkbox-column-action">
                      <a-button size="small" type="primary" @click="setCheckboxColumn">{{trans('Grid.confirm')}}</a-button>
                      <a-button size="small" @click="resetCheckboxColumn">{{trans('Grid.reset')}}</a-button>
                      <a-popconfirm
                          :title="trans('Grid.defaultCheckboxColumnConfirm')"
                          @confirm="clearCheckboxColumn"
                      >
                        <a-button size="small">{{ trans('Grid.defaultCheckboxColumn') }}</a-button>
                      </a-popconfirm>
                    </div>
                  </a-menu>
            </template>
          </a-dropdown>
        </div>
      </div>
      <!--筛选-->
      <div class="filter" v-if="filter" v-show="expandFormFilter && !hideFilter">
        <render :data="filter"></render>
      </div>
      <!-- 表格 -->
      <a-list v-if="custom" :data-source="tableData" :loading="loading" v-bind="custom.attribute"
              :row-key="attrs.rowKey" @scroll="scrollPage" ref="dragTable" class="ex_scrollbar" :style="scroll.y?'height:'+scroll.y+'px':''">
        <template #header v-if="custom.attribute.header">
          <render :data="custom.attribute.header"></render>
        </template>
        <template #loadMore v-if="loadMore">
          <div class="scroll-bottom-tips">
            <a-typography-text type="secondary">
              <span v-if="loading">{{trans('Grid.loading')}}</span>
              <span v-else @click="loadingMore">{{loadMorePage?trans('Grid.loadingMore'):trans('Grid.noMore')}}</span>
            </a-typography-text>
          </div>
        </template>
        <template #renderItem="{ item, index }">
          <a-list-item :style="custom.attribute.itemStyle">
            <template v-if="custom.attribute.container">
              <component :is="custom.attribute.container">
                <render :data="item.custom"></render>
                <div class="custom-action" v-if="item.ExAdminAction">
                  <component v-if="!hideSelection" :is="selectionType=='checkbox'?'ACheckbox':'ARadio'"
                             :checked="selectIds.indexOf(item[attrs.rowKey]) > -1"
                             @change="e=>onSelect(e.target.checked,[item])"></component>
                  <render v-if="item.ExAdminAction" :data="item.ExAdminAction"></render>
                </div>
              </component>
            </template>
            <template v-else>
              <render :data="item.custom"></render>
              <div class="custom-action" v-if="item.ExAdminAction">
                <component v-if="!hideSelection" :is="selectionType=='checkbox'?'ACheckbox':'ARadio'"
                           :checked="selectIds.indexOf(item[attrs.rowKey]) > -1"
                           @change="e=>onSelect(e.target.checked,[item])"></component>
                <render v-if="item.ExAdminAction" :data="item.ExAdminAction"></render>
              </div>
            </template>
          </a-list-item>
        </template>
        <template #footer v-if="custom.attribute.footer">
          <render :data="custom.attribute.footer"></render>
        </template>
      </a-list>
      <!--手机-->
      <a-list v-else-if="state.isMobile" size="small" item-layout="vertical" :data-source="tableData" :loading="loading" class="mobile-list" v-bind="$attrs">
        <template #renderItem="{item}">
          <a-list-item>
            <div v-for="column in tableColumns" style="padding: 15px 10px;font-size: 14px;display: flex">
              <div v-if="column.title" style="margin-right: 5px;color: #888888">{{column.title}}<span>:</span></div>
              <render :data="item[column.dataIndex]"></render>
            </div>
          </a-list-item>
        </template>
      </a-list>

      <!--表格-->
      <a-table v-else
               :custom-row="customRow"
               v-bind="$attrs"
               :row-selection="rowSelection"
               :dataSource="tableData"
               :columns="tableColumns"
               :pagination="false"
               :loading="loading"
               :scroll="scroll"
               v-model:expandedRowKeys="expandedRowKeys"
               @change="tableChange"
               @resizeColumn="handleResizeColumn"
               class="ex-table"
               ref="dragTable">
        <!-- title -->
        <template #title v-if="header">
          <render v-for="item in header" :data="item"></render>
        </template>
        <!-- header -->
        <template #headerCell="{ column }">
          <render :data="column.header" :style="column.width ? '':'white-space:nowrap;display:block'"></render>
        </template>
        <!--列筛选 -->
        <template #customFilterDropdown="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }">
          <render :data="column.customFilterForm" :context="proxyData" @success="columnFilter(confirm)"></render>
        </template>
        <!-- 列筛选图标 -->
        <template #customFilterIcon="{ filtered ,column}">
          <filter-filled
              :style="{ color: empty(proxyData[filter.bindAttribute.model][column.dataIndex]) ?  undefined :'#108ee9'  }"/>
        </template>
        <!-- 可展开 -->
        <template #expandedRowRender="{ record }" v-if="attrs.expandedRow">
          <render :data="record.ExAdminExpandRow"></render>
        </template>
        <!-- body -->
        <template #bodyCell="{ column, record , text , index }">
          <slot name="bodyCell" :column="column" :record="record" :text="text" :index="index"></slot>
          <div v-if="column.type == 'sortDrag'" class="sortDrag">
            <a-tooltip placement="right" :title="trans('Grid.sortTop')">
              <caret-up-outlined style="cursor: pointer" @click="sortTop(index,record[attrs.rowKey],column.dataIndex)"/>
            </a-tooltip>
            <a-tooltip placement="right" :title="trans('Grid.sortDrag')">
              <drag-outlined class="sortHandel" :data-field="column.dataIndex" style="font-weight:bold;cursor: grab"/>
            </a-tooltip>
            <a-tooltip placement="right" :title="trans('Grid.sortBottom')">
              <caret-down-outlined style="cursor: pointer"
                                   @click="sortBottom(index,record[attrs.rowKey],column.dataIndex)"/>
            </a-tooltip>
          </div>
          <template v-else-if="column.type == 'sortInput'">
            <a-input v-model:value="text.content.default[0]"
                     @change="sortInput(record[attrs.rowKey],text.content.default[0],column.dataIndex)"></a-input>
          </template>
          <template v-else>
            <render :data="text"></render>
          </template>
        </template>
        <!-- 统计行 -->
        <template #summary v-if="summaryRow">
          <render :data="summaryRow"></render>
        </template>
        <!-- footer -->
        <template #footer v-if="footer">
          <render v-for="item in footer" :data="item"></render>
        </template>
      </a-table>
      <!-- 分页 -->
      <render :class="['pagination',custom && custom.attribute.customStyle != 'card'?'custom':'']"
              v-if="!hidePage && !loadMore"
              :data="pagination"
              v-model:current="page"
              v-model:pageSize="pageSize"
              :total="total"
              @change="changePage"
      ></render>

      <!-- 导出弹窗 -->
      <a-modal :afterClose="exportClose" :maskClosable="false" :keyboard="false" :footer="null"
               v-model:visible="exportAttr.visible" :title="trans('Grid.exportProgress')">
        <div style="text-align: center">
          <a-progress type="circle" :percent="exportAttr.percent" :status="exportAttr.status"/>
          <div style="margin-top: 10px">
            <div v-if="exportAttr.status == 'success'">
              {{ trans('Grid.exportSuccess') }}
              <a-typography-link :href="exportAttr.url" target="_blank">{{ trans('Grid.download') }}</a-typography-link>
            </div>
            <div v-else-if="exportAttr.status == 'exception'" style="color: red">{{ trans('Grid.exportFail') }}</div>
          </div>
        </div>
      </a-modal>
      </div>
    </a-col>
  </a-row>
</template>
<script>
export default {
  inheritAttrs: false,
  name: 'ExGrid'
}
</script>
<script setup>
import draggable from 'vuedraggable'
import {useInjectState} from '@/store/index'
import {forEach} from 'lodash'
import {useVModel} from '@vueuse/core'
import Sortable from 'sortablejs'
import useHttp from '@/hook/use-http'
import {Modal, message} from 'ant-design-vue'
import md5 from 'js-md5'
import {
  ref,
  computed,
  useAttrs,
  unref,
  nextTick,
  onBeforeUnmount,
  getCurrentInstance,
  reactive,
  watch,
  triggerRef
} from 'vue'
import {trans, deleteArr, empty, offsetTop, getPopupEl, arrFind, jump} from "@/utils";
import request from '@/utils/axios'
import {uniq, debounce,cloneDeep} from 'lodash'
import {useProvideGridContext} from "./context";
import {useInjectRenderContext} from "@/components/render/context";
import { useElementSize } from '@vueuse/core'
const state = useInjectState()
const emit = defineEmits(['update:selection', 'update:selectedSidebar', 'update:expandFilter','update:expandedRowKeys'])
const props = defineProps({
  pagination: Object,
  dataSource: Array,
  columns: Array,
  hidePage: Boolean,
  quickSearchText: String,
  addButton: [Object, Boolean],
  quickSearch: Boolean,
  hideDeleteSelection: Boolean,
  hideAdd: Boolean,
  hideDelete: Boolean,
  hideTrashedDelete: Boolean,
  hideTrashedRestore: Boolean,
  hideFilter: Boolean,
  hideSelection: Boolean,
  expandFilter: Boolean,
  hideTools: Boolean,
  hideExport: Boolean,
  queueExport: Boolean,
  hideExportCurrentPage: Boolean,
  hideExportSelection: Boolean,
  hideExportAll: Boolean,
  hideRefresh: Boolean,
  hideTrashed: Boolean,
  autoHeight: Boolean,
  sidebar: Object,
  selectedSidebar: [String, Number],
  selection: {
    type: Array,
    default: []
  },
  selectionActions:[Boolean,Object],
  selectionField: String,
  selectionLimit: {
    type: Number,
    default: 0
  },
  selectionType: {
    type: String,
    default: 'checkbox'
  },
  filter: [Object, Boolean],
  header: [Object, Boolean],
  footer: [Object, Boolean],
  tools: [Object, Boolean],
  summaryRow: [Object, Boolean],
  url: String,
  //自定义视图
  custom: [Object, Boolean],
  //加载更多仅自定义有效
  loadMore:Boolean,
  params: {
    type: Object,
    default: {},
  },
  callParams: {
    type: Object,
    default: {},
  },
  scroll: {
    type: Object,
    default: {},
  },
  expandedRowKeys:{
    type: Array,
    default: [],
  },
  hideColumns:{
    type: Array,
    default: [],
  }
})
const el = ref(null)
const elementSize = useElementSize(el)

watch(elementSize.height,(value)=>{
  if(props.autoHeight){
    autoHeight()
  }
})
const instance = getCurrentInstance()
useProvideGridContext(instance)
const proxyData = useInjectRenderContext()
//控制加载更多标识
const loadMorePage = ref(true)
let sortable = null
//表格排序参数
let sortableParams = {}

const {loading, http} = useHttp()
const attrs = useAttrs()
//导出进度弹窗
const exportAttr = reactive({
  visible: false,
  status: '',
  percent: 0,
  timer: null,
  url: '',
})
//header
const header = ref(props.header)
//footer
const footer = ref(props.footer)
//tools
const tools = ref(props.tools)
//统计行
const summaryRow = ref(props.summaryRow)
//addButton
const addButton = ref(props.addButton)
//表格数据
const tableData = ref(packageData(props.dataSource))
watch(()=>props.dataSource,function (value){
  tableData.value = packageData(value)
})
//快捷搜索
const quickSearchValue = ref('')

const expandFormFilter = ref(props.expandFilter)
//分页
const page = ref(1)
//分页大小
const pageSize = ref(props.pagination.attribute.pageSize)
//分页总数
const total = ref(props.pagination.attribute.total)
//回收站状态
const trashed = ref(false)

const scroll = ref(cloneDeep(props.scroll))
//表格已选择项
const selectIds = ref(props.selection)
const selections = ref(props.selection)
//侧边栏选中值
const sidebarValue = ref()
watch(sidebarValue, value => {
  emit('update:selectedSidebar', value)
  requestData()
})
//表格列列显示
const checkboxColumnVisible = ref(false)
let checkboxColumnRestConfig = []
watch(checkboxColumnVisible,value=>{
  if(value){
    checkboxColumnRestConfig = cloneDeep(checkboxColumns.value)
  }
})
//表格列
const originColumns = cloneDeep(props.columns)
const columns = useVModel(props, 'columns', emit)
const checkboxColumns = ref([])
watch(()=>props.columns,value=>{
  initColumns()
})
initColumns()
function initColumns(){
  columns.value.forEach(item=>{
    if(!item.hasOwnProperty('checkboxColumnShow')){
      item.checkboxColumnShow = true
    }
    if(!item.hasOwnProperty('hide')){
      item.hide = props.hideColumns.indexOf(item.dataIndex) > -1;
    }
  })
  checkboxColumns.value = cloneDeep(columns.value)
}
function checkboxColumnKey(){
  const col = originColumns.map(item=>{
    return {
      dataIndex:item.dataIndex,
      title:item.title,
    }
  })
  return md5(JSON.stringify(props.hideColumns) + JSON.stringify(col) + JSON.stringify(callParams()) + state.systemInfo.id)
}
function setCheckboxColumn(){
  if(state.systemInfo){
    const key = checkboxColumnKey()
    request({
      url:'ex-admin/system/operationCache',
      method:'post',
      data:{
        type:'set',
        params:[key, checkboxColumns.value]
      }
    }).then(()=>{
      columns.value = cloneDeep(checkboxColumns.value)
      checkboxColumnVisible.value = false
    })
  }
}
function loadCheckboxColumn(){
  const key = checkboxColumnKey()
  request({
    url:'ex-admin/system/operationCache',
    method:'post',
    data:{
      type:'get',
      params:[key]
    }
  }).then((res)=>{
    const config = res.data
    if(config){
      checkboxColumns.value = config.map(item=>{
        const column = {...arrFind(originColumns,'dataIndex',item.dataIndex)}
        column.hide = item.hide
        return column
      })
      columns.value = cloneDeep(checkboxColumns.value)
    }
  })
}
function resetCheckboxColumn(){
  checkboxColumns.value = cloneDeep(checkboxColumnRestConfig)
}
function clearCheckboxColumn(){
  request({
    url:'ex-admin/system/operationCache',
    method:'post',
    data:{
      type:'delete',
      params:[checkboxColumnKey()]
    }
  }).then(()=>{
    columns.value = cloneDeep(originColumns)
    checkboxColumns.value = cloneDeep(originColumns)
    checkboxColumnVisible.value = false
  })
}
loadCheckboxColumn()
//展开的行，控制属性
const expandedRowKeys = useVModel(props, 'expandedRowKeys', emit)
defaultExpandAllRows()
function childrenColumnName(){
  return attrs.childrenColumnName || 'children'
}
function findAllChildrenKeys(data){

  var keys = [];
  function dig(list) {
    (list || []).forEach(function (item) {
      keys.push(item[attrs.rowKey]);
      dig(item[childrenColumnName()]);
    });
  }
  dig(data)
  return keys
}
function packageData(data){
  function dig(list) {
    (list || []).forEach(function (item) {
      for (let key in item){
        if(key != 'dblclickAction'){
          if(typeof(item[key]) == 'object' && !item.hide && item.dblclickAction){
            item[key].content.default.push({
              name:'html',
              attribute:{
                style:{
                  display:'none'
                }
              },
              content:{
                default:[item.dblclickAction]
              }
            })
            break
          }
        }
      }
      dig(item[childrenColumnName()]);
    });
  }
  dig(data)
  return data
}
function defaultExpandAllRows(){

  if(attrs.defaultExpandAllRows){
    expandedRowKeys.value = findAllChildrenKeys(tableData.value)
  }
}

watch(page,value=>{
  if(value == 1){
    loadMorePage.value = true
  }
})


const dragTable = ref()
//表格列
const tableColumns = computed(() => {
  return columns.value.filter(item => {
    return (item.dataIndex == 'ExAdminAction' || !item.hide) && !item.onlyExport
  })
})

function selectCheckboxColumn(field) {
  columns.value.forEach(item=>{
    if(item.dataIndex == field){
      item.hide = false
    }
  })
}

function onSelect(selected, selectedRows) {
  selectedRows = selectedRows.filter(item=>{
    return item !== undefined
  })


  onSelection(selectIds, attrs.rowKey, selected, selectedRows)
  onSelection(selections, 'ex_admin_selected', selected, selectedRows)

  emit('update:selection', selections.value)
}
//控制展开行
function changeExpandedRow(id){
  if(expandedRowKeys.value.indexOf(id) === -1){
    expandedRowKeys.value.push(id)
  }else{
    deleteArr(expandedRowKeys.value, id)
  }
}
function onSelection(proxy, key, selected, selectedRows) {

  const ids = selectedRows.map(item => {
    return item[key]
  })
  if (selected) {
    if (props.selectionType === 'checkbox') {
      proxy.value = uniq(proxy.value.concat(ids))
      if (props.selectionLimit > 0) {
        proxy.value = proxy.value.slice(0, props.selectionLimit)
      }
    } else {
      proxy.value = ids

    }
  } else {
    ids.map(id => {
      deleteArr(proxy.value, id)
    })
  }

}

//自定义选择项
const rowSelection = computed(() => {
  if (props.hideSelection) {
    return null
  } else {
    return {
      fixed:true,
      selectedRowKeys: unref(selectIds),
      type: props.selectionType,
      //当用户手动勾选数据行的 Checkbox 时触发的事件
      onSelect: (record, selected, selectedRows, nativeEvent) => {
        if (selected) {
          onSelect(selected, selectedRows)
        } else {
          onSelect(selected, [record])
        }
      },
      onSelectAll: (selected, selectedRows, changeRows) => {
        if (selected) {
          onSelect(selected, selectedRows)
        } else {
          onSelect(selected, changeRows)
        }
      },
    }
  }
})

//分页改变
function changePage(number) {
  requestData()
}

//快捷搜索
function handleFilter() {
  page.value = 1
  requestData()
}

//删除全部
function deleteAll() {
  Modal.confirm({
    title: trans('Grid.continue'),
    content: trans('Grid.confirmClear'),
    onOk() {
      request({
        url: props.url,
        method: 'delete',
        data: Object.assign(requestDataParams(),{
          ids: [],
          ex_admin_action: 'delete',
          all: true,
        })
      }).then(res => {
        selectIds.value = []
        requestData()
      })
    }
  })
}

//删除选中
function deleteSelect() {
  Modal.confirm({
    title: trans('Grid.continue'),
    content: trans('Grid.confirmClearSelected'),
    onOk() {
      request({
        url: props.url,
        method: 'delete',
        data: Object.assign(requestDataParams(),{
          ex_admin_action: 'delete',
          ids: selectIds.value,
          all: false,
        })
      }).then(res => {
        selectIds.value = []
        requestData()
      })
    }
  })
}

//恢复选中
function recoverySelect() {
  Modal.confirm({
    title: trans('Grid.continue'),
    content: trans('Grid.confirmRecoverySelected'),
    onOk() {
      request({
        url: props.url,
        method: 'post',
        data: callParams({
          ex_admin_action: 'restore',
          ids: selectIds.value
        })
      }).then(res => {
        selectIds.value = []
        requestData()
      })
    }
  })
}

function callParams(params) {
  let requestParams = {ex_admin_trashed: trashed.value}
  Object.assign(requestParams, props.callParams, params)
  if (sidebarValue.value !== undefined) {
    requestParams[props.sidebar.attribute.field] = sidebarValue.value
  }
  return requestParams
}

function requestParams() {
  let requestParams = {
    grid_request_data: true,
    ex_admin_page: page.value,
    ex_admin_size: pageSize.value,
    quickSearch: quickSearchValue.value,
  }
  let filterData = {}
  if (props.filter) {
    filterData = proxyData[props.filter.bindAttribute.model] || {}

    if (sidebarValue.value !== undefined) {
      filterData[props.sidebar.attribute.field] = sidebarValue.value
    }
  }
  Object.assign(requestParams, props.params, sortableParams, {ex_admin_filter: filterData})

  return requestParams
}
//请求参数包含所有条件
function requestDataParams(){
  return callParams(requestParams())
}
//请求加载数据
function requestData() {
  http({
    url: props.url,
    method: 'post',
    data: Object.assign({_ajax: 'get',GRID_REF : attrs.grid_ref}, requestDataParams()),
  }).then(res => {
    originColumns.forEach(item=>{
      if(!item.width){
        let action = arrFind(columns.value,'dataIndex',item.dataIndex)
        if(action.width){
          delete action.width
        }
      }
    })
    if(props.loadMore && props.custom && page.value > 1){
      if(res.data.length != pageSize.value){
        loadMorePage.value = false
      }
      if(res.data.length > 0){
        tableData.value = tableData.value.concat(packageData(res.data))
      }
    }else{
      tableData.value = packageData(res.data)
    }

    total.value = res.total
    summaryRow.value = res.summaryRow
    if (attrs.headerRefresh) {
      header.value = res.header
    }
    if (attrs.footerRefresh) {
      footer.value = res.footer
    }
    if (attrs.toolsRefresh) {
      tools.value = res.tools
    }
    addButton.value = res.addButton
    if(!props.custom){
      defaultExpandAllRows()
      tableInit()
    }
  })
}
tableInit()
function tableInit() {
  if(scroll.value.y){
    delete scroll.value.y
  }
  nextTick(() => {
    if (!props.custom){
      dragSort()
    }
    if(!state.isMobile) {
      tableAutoWidth()
    }
  })
}
onBeforeUnmount((e) => {
  if (sortable) {
    sortable.destroy()
  }
  exportClose()
})
let popupHeight = null
function autoHeight() {
  if(tableData.value.length === 0){
    return
  }
  try {
    if (props.scroll.y || props.autoHeight) {
      columns.value.forEach((column, index) => {
        let width = 0
        if (!column.width && column.dataIndex !== 'ExAdminAction') {

          forEach(document.getElementsByClassName('ex_admin_table_th_' + column.dataIndex), item => {
            let offsetWidth = item.parentNode.offsetWidth

            if (width < offsetWidth) {
              width = offsetWidth
            }
          })
          forEach(document.getElementsByClassName('ex_admin_table_td_' + column.dataIndex), item => {
            if (width < item.parentNode.offsetWidth) {
              width = item.parentNode.offsetWidth
            }
          })
          column.width = width+1
        }
        if (column.dataIndex === 'ExAdminAction' && dragTable.value && !column.fixed) {
          nextTick(() => {
            setTimeout(()=>{
              const tableEl = dragTable.value.table.$el
              const selector = getTableSelector()
              const el = tableEl.querySelectorAll(`.${selector}`)[0]
              const table = tableEl.querySelectorAll(`.${selector} > table`)[0]
              if (table.clientWidth > el.clientWidth) {
                column.fixed = 'right'
                triggerRef(columns)
              }
            })
          })
        }
      })
    }

    //自适应最大高度
    if (!props.scroll.y && props.autoHeight) {
      const el = props.custom ? dragTable.value.$el:dragTable.value.table.$el
      const popupEl = getPopupEl(el)
      let offsetHeight = props.custom ?0:20
      if (popupEl) {
        if(!popupHeight){
          popupHeight = popupEl.offsetHeight
        }
        offsetHeight +=25
        scroll.value.y = popupHeight - offsetTop(el, ['ant-modal', 'ant-drawer']) - (props.hidePage || (props.loadMore && props.custom) ? 0 : 45) - offsetHeight
      } else {
        scroll.value.y = window.innerHeight - offsetTop(el) - (props.hidePage || (props.loadMore && props.custom) ? 40 : 85) - offsetHeight
      }
      triggerRef(columns)
      nextTick(()=>{
        dragSort()
      })
    }
  } catch (e) {
    console.log(e)
  }
}

function tableAutoWidth() {
  const tableEl = dragTable.value.table.$el
  columns.value.forEach(item => {
    if (item.dataIndex === 'ExAdminAction' && !item.width) {
      let width = 0
      let actionColumn = tableEl.getElementsByClassName('ExAdminAction')
      if (actionColumn.length > 0) {
        actionColumn = Array.from(actionColumn)
        actionColumn.forEach(row => {
          let offsetWidth = row.offsetWidth
          if (width < offsetWidth) {
            width = offsetWidth
          }
        })

        item.width = width + 35
      }
      //有滚动条操作列fixed
      if (!item.fixed) {
        const selector = getTableSelector()
        const el = tableEl.querySelectorAll(`.${selector}`)[0]
        const table = tableEl.querySelectorAll(`.${selector} > table`)[0]
        if (table.clientWidth > el.clientWidth) {
          item.fixed = 'right'
        }
      }
      //高度自适应
      if (props.autoHeight || item.fixed || props.scroll.y) {
        autoHeight()
      }

    }
  })
  triggerRef(columns)

}

function visibleFilter() {
  expandFormFilter.value = !expandFormFilter.value
  emit('update:expandFilter', !props.expandFilter)

}

function getTableSelector() {
  if (scroll.value.y) {
    return 'ant-table-body'
  }
  return 'ant-table-content'
}

//拖拽排序
function dragSort() {
  if (dragTable.value && dragTable.value.table) {
    let el = dragTable.value.table.$el
    const selector = getTableSelector()
    el = el.querySelectorAll(`.${selector} > table > tbody`)[0]
    sortable = Sortable.create(el, {
      animation: 1000,
      handle: '.sortHandel',
      //ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
      onEnd: evt => {
        var newIndex = evt.newIndex - 1;
        var oldIndex = evt.oldIndex - 1;
        var oldItem = tableData.value[oldIndex]
        var startPage = (page.value - 1) * pageSize.value
        const targetRow = tableData.value.splice(oldIndex, 1)[0]
        tableData.value.splice(newIndex, 0, targetRow)
        if (oldIndex != newIndex) {
          let field
          if (el.getElementsByClassName('sortHandel').length) {
            field = el.getElementsByClassName('sortHandel')[0].dataset.field
          }
          sortRequest(oldItem[attrs.rowKey], startPage + newIndex, field).catch(() => {
            const targetRow = tableData.value.splice(newIndex, 1)[0]
            tableData.value.splice(oldIndex, 0, targetRow)
          })
        }
      }
    })

  }
}

const sortInput = debounce(sortInputRequest, 300)

//输入框排序
function sortInputRequest(id, sort, field) {
  request({
    url: props.url,
    method: 'post',
    data: callParams({
      ex_admin_action: 'inputSort',
      id: id,
      field: field,
      sort: parseInt(sort),
    })
  })
}

//排序置顶
function sortTop(index, id, field) {
  sortRequest(id, 0, field).then(res => {
    if (page.value === 1) {
      const targetRow = tableData.value.splice(index, 1)[0]
      tableData.value.unshift(targetRow)
    } else {
      tableData.value.splice(index, 1)
    }
  })

}

//排序置底
function sortBottom(index, id, field) {
  sortRequest(id, total.value - 1, field).then(res => {
    if (page.value === 1) {
      const targetRow = tableData.value.splice(index, 1)[0]
      tableData.value.push(targetRow)
    } else {
      tableData.value.splice(index, 1)
    }

  })
}

function sortRequest(id, sort, field) {
  return new Promise((resolve, reject) => {
    request({
      url: props.url,
      method: 'post',
      data: callParams({
        ex_admin_action: 'dragSort',
        id: id,
        field: field,
        sort: sort,
      })
    }).then(res => {
      resolve(res)
    }).catch(res => {
      reject(res)
    })
  })
}

//表格分页、排序、筛选变化时触发事件
function tableChange(pagination, filters, sorter) {
  if (sorter.order === 'descend') {
    sortableParams = {
      ex_admin_sort_field: sorter.field,
      ex_admin_sort_by: 'desc'
    }

  } else if (sorter.order === 'ascend') {
    sortableParams = {
      ex_admin_sort_field: sorter.field,
      ex_admin_sort_by: 'asc'
    }
  } else {
    sortableParams = {}
  }
  requestData()
}

//点击导出
function handleExport({key}) {
  if (tableData.value.length == 0) {
    message.warning(trans('Grid.empty'))
    return false
  }
  let all = false
  let ids = []
  if (key == 'all') {
    all = true
  } else if (key == 'select') {
    ids = cloneDeep(selectIds.value)
    selectIds.value = []
  } else if (key == 'page') {
    ids = tableData.value.map(item => item[attrs.rowKey])
  }
  request({
    url: props.url,
    method: 'post',
    data: callParams(Object.assign(requestParams(), {
      ex_admin_action: 'export',
      ex_admin_export: true,
      columns: columns.value.filter(item => {
        return !item.closeExport && (item.onlyExport || !item.hide)
      }),
      selectIds: ids,
      all: all,
      ex_admin_queue: props.queueExport
    }))
  }).then(res => {
    exportAttr.status = ''
    exportAttr.percent = 0
    exportAttr.visible = true
    exportAttr.timer = setInterval(() => {
      request({
        url: '/ex-admin/system/exportProgress',
        method: 'post',
        data: {
          key: res.data.key
        }
      }).then(result => {
        if (result.data.status == 0) {
          exportAttr.percent = result.data.progress
        } else if (result.data.status == 1) {
          exportAttr.status = 'success'
          exportAttr.percent = 100
          exportAttr.url = result.data.url
          exportClose()
        } else if (result.data.status == 2) {
          exportAttr.status = 'exception'
          exportClose()
        }
      })
    }, 500)
  })
}

//列筛选
function columnFilter(confirm) {
  confirm()
}


//回收站
function trashedHandel() {
  trashed.value = !trashed.value
  requestData()
}

//关闭导出弹窗
function exportClose() {
  if (exportAttr.timer != null) {
    clearInterval(exportAttr.timer)
  }
}
//刷新数据
function refresh(resetPage = false){
  if(resetPage || props.loadMore){
    page.value = 1
  }
  selectIds.value = []
  requestData()
}
//设置行属性
function customRow(record, index){
  return {
      onDblclick: (event) => {
        if(record.dblclickAction){
          if(['AModal','ADrawer'].indexOf(record.dblclickAction.name) > -1){
            record.dblclickAction.initModal()
          }else if(record.dblclickAction.directive){
            record.dblclickAction.directive.forEach(item=>{
              if(item.name == 'redirect'){
                return jump(item.value)
              }
            })
          }
        }
      },
  }
}
//拖动列宽度
function handleResizeColumn(w, col){
  col.width = w
  triggerRef(columns)
}
//滚动分页
function scrollPage(e){
  let el = e.target
  if((el.scrollTop + el.clientHeight) == el.scrollHeight){
    loadingMore()
  }
}
//加载更多
function loadingMore(){
  if(props.loadMore && !loading.value && loadMorePage.value){
    page.value++
    requestData()
  }
}
function checkboxColumnSearch(e){
  columns.value.forEach(item=>{
    if(item.title){
      item.checkboxColumnShow = item.title.indexOf(e.target.value) > -1
    }

  })
}
defineExpose({
  requestDataParams,
  selectCheckboxColumn,
  requestData,
  handleFilter,
  refresh,
  selectIds,
  onSelect,
  changeExpandedRow,
})
</script>

<style scoped lang="scss">
.grid {
  display: flex;
}
.quickSearch{
  margin-right: 8px;
  width: 250px;
}
.filter {
  border-top: 1px solid #ededed;
  background: #fff;
  padding: 20px 20px 0px;
}

.filter .form {
  padding: 0;
}

.filter .ant-form-inline :deep(.ant-form-item) {
  margin-bottom: 20px;
}

.tools {
  background: #fff;
  position: relative;
  border-radius:5px 5px 0 0 ;
  padding-left: 10px;
  padding-bottom: 10px;
  padding-top: 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}
.tools .left{
  flex:1;
  display: flex;
  flex-wrap: wrap;
}
.tools .right {
  display: flex;
  justify-content: end;
  margin: 0 15px;
}

.pagination {
  background: #fff;
  padding: 10px 15px;

  border-radius:0 0 5px 5px;
}

.dark-theme {
  .pagination, .tools {
    background: #141414;
  }

  .filter {
    border-top: 1px solid #434343;
    background: #141414;
  }
}

.sortDrag {
  display: flex;
  flex-direction: column;
}

.custom {
  background: none !important;
  padding-left: 0 !important;
  padding-top: 0 !important;
}
.light-theme{
  .mobile-list{
    background: #fff;
    border-top: 1px solid #f0f0f0;
    border-bottom: 1px solid #f0f0f0;
  }
}
.dark-theme{
  .mobile-list{

    border-top: 1px solid #303030;
    border-bottom: 1px solid #303030;
  }
}

.custom-action {
  margin-top: 15px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.light-theme {
  .ex-table :deep(.table-striped) td {
    background-color: #fafafa;
  }
}
.dark-theme{
  .ex-table :deep(.table-striped) td {
    background-color: #000000;
  }
}
.scroll-bottom-tips{
  cursor: pointer;
  text-align: center;
}
.checkbox-column-content{
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.checkbox-column-action{
  display: flex;
  justify-content: end;
  align-items: center;
  margin: 5px 5px 0 5px ;
}
</style>
